home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk.zip / JMP.C < prev    next >
C/C++ Source or Header  |  1991-04-07  |  6KB  |  218 lines

  1.  
  2. /********************************************
  3. jmp.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the Awk programming language as defined in
  8. Aho, Kernighan and Weinberger, The AWK Programming Language,
  9. Addison-Wesley, 1988.
  10.  
  11. See the accompaning file, LIMITATIONS, for restrictions
  12. regarding modification and redistribution of this
  13. program in source or binary form.
  14. ********************************************/
  15.  
  16. /* $Log:    jmp.c,v $
  17.  * Revision 2.1  91/04/08  08:23:19  brennan
  18.  * VERSION 0.97
  19.  * 
  20. */
  21.  
  22. /* this module deals with back patching jumps, breaks and continues,
  23.    and with save and restoring code when we move code.
  24.    There are three stacks.  If we encounter a compile error, the
  25.    stacks are frozen, i.e., we do not attempt error recovery
  26.    on the stacks
  27. */
  28.  
  29.  
  30. #include "mawk.h"
  31. #include "jmp.h"
  32. #include "code.h"
  33. #include "sizes.h"
  34. #include "init.h"
  35. #include "memory.h"
  36.  
  37. extern unsigned compile_error_count ;
  38. #define error_state  (compile_error_count>0)
  39.  
  40.  
  41. /* a stack to hold jumps that need to be patched */
  42.  
  43. #define JMP_STK_SZ  (2*MAX_LOOP_DEPTH)
  44.  
  45. static INST **jmp_stack ; 
  46. static INST **jmp_sp  ;
  47.  
  48. /*-------------------------------------*/
  49. /* a stack to hold break or continue that need to be
  50.    patched (which is all of them) */
  51.  
  52. #define  BC_SZ    MAX_LOOP_DEPTH
  53.  
  54. /* the stack holds a linked list of these */
  55.  
  56. struct BC_node { /* struct for the break/continue list */
  57. char type ;   /*  'B' or 'C' */
  58. INST *jmp ;   /*  the jump to patch */
  59. struct BC_node *link ;
  60. } ;
  61.  
  62. static   struct BC_node  **BC_stack ;
  63. static   struct BC_node  **BC_sp ;
  64.  
  65. /*---------------------------------------*/
  66. /* a stack to hold some pieces of code while 
  67.    reorganizing loops */
  68.  
  69. #define  LOOP_CODE_SZ    (2*MAX_LOOP_DEPTH)
  70.  
  71. static struct loop_code {
  72. INST *code ;
  73. unsigned short len ;
  74. }  *loop_code_stack , *lc_sp ;
  75.  
  76. /*--------------------------------------*/
  77. void jmp_stacks_init()
  78. { jmp_stack = (INST **)  zmalloc(JMP_STK_SZ*sizeof(INST*)) ;
  79.   jmp_sp = jmp_stack-1 ;
  80.  
  81.   BC_stack = (struct BC_node **) 
  82.               zmalloc(BC_SZ*sizeof(struct BC_node*)) ;
  83.   BC_sp =  BC_stack-1 ;
  84.  
  85.   loop_code_stack = (struct loop_code *)
  86.                     zmalloc(LOOP_CODE_SZ*sizeof(struct loop_code)) ;
  87.   lc_sp = loop_code_stack - 1 ;
  88. }
  89.  
  90. void jmp_stacks_cleanup()
  91. { zfree(jmp_stack, JMP_STK_SZ*sizeof(INST*)) ;
  92.   zfree(BC_stack, BC_SZ*sizeof(struct BC_node*)) ;
  93.   zfree(loop_code_stack, LOOP_CODE_SZ*sizeof(struct loop_code)) ;
  94. }
  95. /*--------------------------------------*/
  96. /* operations on the jmp_stack */
  97.  
  98. void code_jmp( jtype, target)
  99.   int jtype ; INST *target ;
  100.   if (error_state)  return ;
  101.  
  102.   /* check if a constant expression will be at top of stack,
  103.      if so replace conditional jump with jump */
  104.  
  105.   if ( code_ptr[-2].op == _PUSHC && jtype != _JMP )
  106.   { int t = test( (CELL *) code_ptr[-1].ptr ) ;
  107.     if ( jtype == _JZ && ! t ||
  108.          jtype == _JNZ && t )
  109.     { code_ptr -= 2 ; jtype = _JMP ; }
  110.   }
  111.    
  112.   if ( ! target ) /* jump will have to be patched later ,
  113.                      put it on the jmp_stack */
  114.   { if ( ++jmp_sp == jmp_stack + JMP_STK_SZ )
  115.           overflow("jmp stack" , JMP_STK_SZ ) ; 
  116.     *jmp_sp = code_ptr ;
  117.     code2(jtype, 0) ;
  118.   }
  119.   else
  120.   { INST *source = code_ptr ;
  121.   
  122.     code_ptr++->op = jtype ;
  123.     code_ptr++->op = target - source ; 
  124.   }
  125. }
  126.  
  127. void patch_jmp(target)  /* patch a jump on the jmp_stack */
  128.   INST *target ;
  129. { register INST *source ;
  130.  
  131.   if ( ! error_state )
  132.   {
  133.     if ( jmp_sp <= jmp_stack-1 ) bozo("jmp stack underflow") ;
  134.     source = *jmp_sp-- ;
  135.     source[1].op = target - source ;
  136.   }
  137. }
  138.  
  139.  
  140. /*---------------------------*/
  141.  
  142. /* a stack of linked lists of BC_nodes for patching 
  143.    break and continue statements.  */
  144.  
  145.  
  146. void BC_new()  /* push an empty list on the stack */
  147.   if ( ! error_state )
  148.   { if ( ++BC_sp == BC_stack + BC_SZ ) overflow("BC stack", BC_SZ) ;
  149.     * BC_sp = (struct BC_node *) 0 ;
  150.   }
  151. }
  152.  
  153. void BC_insert(type, address)
  154.   int type ; INST *address ;
  155. { register struct BC_node *p ; 
  156.  
  157.   if ( error_state )  return ;
  158.   if ( BC_sp <= BC_stack - 1 )
  159.   {  compile_error(  type == 'B' ?
  160.         "break statement outside of loop" :
  161.         "continue statement outside of loop" ) ; 
  162.      return ;
  163.   }
  164.   
  165.   p = (struct BC_node *) zmalloc( sizeof(struct BC_node) ) ;
  166.   p->type = type ; p->jmp = address ;
  167.   p->link = *BC_sp ; *BC_sp = p ;
  168. }
  169.  
  170. void BC_clear(B_address, C_address)  
  171. /* patch all break and continues on list */
  172. INST *B_address, *C_address ;
  173. { register struct BC_node *p , *q ;
  174.  
  175.   if (error_state) return ;
  176.   if ( BC_sp <= BC_stack-1) bozo("underflow on BC stack") ;
  177.   p = *BC_sp-- ;
  178.   while ( p )
  179.   { p->jmp[1].op = (p->type=='B' ? B_address : C_address) - p->jmp ;
  180.     q = p ; p = p->link ; zfree(q, sizeof(struct BC_node)) ;
  181.   }
  182. }
  183.  
  184. /*---------------------------------------------*/
  185. /*  save and restore some code for reorganizing
  186.     loops on a stack */
  187.  
  188.  
  189. void code_push( p, len)
  190.   INST *p ; unsigned len ;
  191.   if (error_state) return ;
  192.   if ( ++lc_sp == loop_code_stack + LOOP_CODE_SZ )
  193.         overflow("loop_code_stack" , LOOP_CODE_SZ) ;
  194.  
  195.   if ( len )
  196.   { lc_sp->code = (INST *) zmalloc(sizeof(INST) * len) ;
  197.     (void) memcpy(lc_sp->code, p, sizeof(INST) * len) ; }
  198.   else  lc_sp->code = (INST *) 0 ;
  199.   lc_sp->len = (unsigned short) len ;
  200. }
  201.  
  202. /* copy the code at the top of the loop code stack to target.
  203.    return the number of bytes moved */
  204.  
  205. unsigned code_pop(target) 
  206.   INST *target ;
  207.   if (error_state)  return 0 ;
  208.   if ( lc_sp <= loop_code_stack-1 )  bozo("loop code stack underflow") ;
  209.   if ( lc_sp->len )
  210.   { (void) memcpy(target, lc_sp->code, lc_sp->len * sizeof(INST)) ;
  211.     zfree(lc_sp->code, sizeof(INST)*lc_sp->len) ; }
  212.   return lc_sp-- -> len ;
  213. }
  214.